//
//  ImageUtility.m
//  EsGUtils
//
//  Created by apple on 14-11-13.
//  Copyright (c) 2014年 ChinaSoftI. All rights reserved.
//

#import "ImageUtility.h"

#define kThumbMaxDataLength_10         10*1024
#define kThumbMaxDataLength_5          5*1024

@implementation ImageUtility

//图片不是方形，从中间截取方形，width＝0的时候按照图片最小的长或宽从中间截取正方形图片，图片with有值，按照with从中间截取正方形图片
+ (UIImage*) createRectangleImageInCenter:(UIImage *)image withWidth:(int)width
{
    int imageWith = (int)image.size.width;
    int imageheight = (int)image.size.height;
    
    if(width==0){
        if (imageWith<imageheight) {
            width = imageWith;
        }else  if (imageWith>imageheight) {
            width = imageheight;
        }else{
            width = imageWith;
        }
    }
    
    CGAffineTransform transform = CGAffineTransformIdentity;
    
    UIImageOrientation orient = image.imageOrientation;
    
    switch(orient) {
        case UIImageOrientationUp:
            transform = CGAffineTransformIdentity;
            break;
        case UIImageOrientationUpMirrored:
            transform = CGAffineTransformMakeTranslation(width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;
        case UIImageOrientationDown:
            transform = CGAffineTransformMakeTranslation(width, width);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformMakeTranslation(0.0, width);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;
        case UIImageOrientationLeftMirrored:
            
            transform = CGAffineTransformMakeTranslation(width, width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;
        case UIImageOrientationLeft:
            
            transform = CGAffineTransformMakeTranslation(0.0, width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;
        case UIImageOrientationRightMirrored:
            
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;
        case UIImageOrientationRight:
            
            transform = CGAffineTransformMakeTranslation(width, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;
        default:
            transform = CGAffineTransformIdentity;
    }
    UIImage *contentView = nil;
    if(orient!=0){
        UIGraphicsBeginImageContext(CGSizeMake(width, width));
        CGContextRef context = UIGraphicsGetCurrentContext();
        if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
            CGContextScaleCTM(context, -1, 1);
            CGContextTranslateCTM(context, -width, 0);
        } else {
            CGContextScaleCTM(context, 1, -1);
            CGContextTranslateCTM(context, 0, -width);
        }
        CGContextConcatCTM(context, transform);
        CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, width), image.CGImage);
        UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        
        
        CGRect rect = CGRectMake((imageWith-width)/2, (imageheight-width)/2, width, width); //创建居中矩形框
        CGImageRef subImageRef = CGImageCreateWithImageInRect(imageCopy.CGImage, rect);
        contentView=[UIImage imageWithCGImage:subImageRef];
        CGImageRelease(subImageRef);
    }else{
        CGRect rect = CGRectMake((imageWith-width)/2, (imageheight-width)/2, width, width); //创建居中矩形框
        CGImageRef subImageRef = CGImageCreateWithImageInRect(image.CGImage, rect);
        contentView=[UIImage imageWithCGImage:subImageRef];
        CGImageRelease(subImageRef);
    }
    
    return contentView;
}



+ (UIImage *)createImageFromRect:(UIImage *)image frame:(CGRect)frame{
    CGImageRef subImageRef = CGImageCreateWithImageInRect(image.CGImage, frame);
    UIImage *contentView=[UIImage imageWithCGImage:subImageRef];
    CGImageRelease(subImageRef);
    return contentView;
}

//缩放图片到width＊width 保持比例不变 保持scale不变
+ (UIImage*) createImageAspect:(UIImage *)image fillWithWidth:(float)maxWidth
{
    if (maxWidth==0) {
        maxWidth = MAX(image.size.width, image.size.height);
    }
    float width = image.size.width*image.scale;
    float height = image.size.height*image.scale;
    CGSize newSize = CGSizeZero;
    maxWidth = maxWidth*2;
    CGFloat percent = MIN(maxWidth/width, maxWidth/height);
    int newWidth = (width * percent);
    int newHeight = height * percent;
    newSize = CGSizeMake(newWidth,newHeight);
    
    
    CGRect rect = CGRectMake(0, 0, newSize.width, newSize.height);
    UIGraphicsBeginImageContext(newSize);
    [image drawInRect:rect];
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return imageCopy;
}


//高或者宽不超过maxWidthOrHeight 保持比例不变
+ (UIImage*)createImageKeepAspect:(UIImage *)image maxWidthOrHeight:(float)maxWidthOrHeight
{
    if (maxWidthOrHeight == 0){
        maxWidthOrHeight = MAX(image.size.width, image.size.height);
    }
    
    float width = image.size.width * image.scale;
    float height = image.size.height * image.scale;
    
    CGSize newSize = CGSizeZero;
    maxWidthOrHeight = maxWidthOrHeight*2;
    CGFloat percent = MIN(maxWidthOrHeight/width, maxWidthOrHeight/height);
    int newWidth = (width * percent);
    int newHeight = height * percent;
    newSize = CGSizeMake(newWidth,newHeight);
    
    CGRect rect = CGRectMake(0, 0, newSize.width, newSize.height);
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    CGContextRef context = CGBitmapContextCreate(NULL, newSize.width, newSize.height,
                                                 8,
                                                 0,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedFirst);
    
    
    CGContextDrawImage(context, rect, image.CGImage);
    
    CGContextSaveGState(context);
    
    CGImageRef newCGImage = CGBitmapContextCreateImage(context);
    UIImage* resultImage =[UIImage imageWithCGImage:newCGImage];
    CGContextRelease(context);
    CGImageRelease(newCGImage);
    CGColorSpaceRelease(colorSpace);
    return resultImage;
    // return [image croppedImage:rect];
}


//缩放图片到width＊width 保持比例不变 保持scale不变
+ (UIImage*)createImageKeepAspectForUpload:(UIImage *)image fillWithWidth:(float)maxWidth
{
    if (maxWidth==0) {
        NSLog(@"maxWidth = %ld,参数有误！",(long)maxWidth );
        return nil;
    }
    
    NSLog(@"原始图片scale:%f", image.scale);
    NSLog(@"原始图片尺寸:%@", NSStringFromCGSize(image.size));
    CGFloat width = image.size.width*image.scale;
    CGFloat height = image.size.height*image.scale;
    CGSize newSize = CGSizeZero;
    
    CGFloat percent = MIN(maxWidth/width, maxWidth/height);
    newSize = CGSizeMake(width * percent,height * percent);
    NSLog(@"等比缩放后尺寸：%@", NSStringFromCGSize(newSize));
    
    CGRect rect = CGRectMake(0, 0, newSize.width, newSize.height);
    UIGraphicsBeginImageContext(newSize);
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextClipToRect(currentContext, rect);
    [image drawInRect:rect];
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    imageCopy = [UIImage imageWithCGImage:imageCopy.CGImage scale:1 orientation:imageCopy.imageOrientation];
    NSLog(@"scale=1时后的尺寸:%@", NSStringFromCGSize(imageCopy.size));
    return imageCopy;
}



// 从中间去方形图片  很快！！！
static UIImage * SquareImageFromImage(UIImage *image) {
    UIImage *squareImage = nil;
    CGSize imageSize = [image size];
    
    if (imageSize.width == imageSize.height) {
        squareImage = image;
    } else {
        // Compute square crop rect
        CGFloat smallerDimension = MIN(imageSize.width, imageSize.height);
        CGRect cropRect = CGRectMake(0, 0, smallerDimension, smallerDimension);
        
        // Center the crop rect either vertically or horizontally, depending on which dimension is smaller
        if (imageSize.width <= imageSize.height) {
            cropRect.origin = CGPointMake(0, rintf((imageSize.height - smallerDimension) / 2.0));
        } else {
            cropRect.origin = CGPointMake(rintf((imageSize.width - smallerDimension) / 2.0), 0);
        }
        
        CGImageRef croppedImageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
        squareImage = [UIImage imageWithCGImage:croppedImageRef];
        CGImageRelease(croppedImageRef);
    }
    
    return squareImage;
}



//变成偶数,防止生成scale＝2的图片时候，大小为奇数
+(int)createEvenInt:(int)num{
    return ((int)((num)/2))*2;
}

//缩放图片到width＊width 保持比例不变 保持scale不变
- (UIImage*) createImageKeepAspect:(UIImage *)image fillWithWidth:(float)maxWidth
{
    if (maxWidth==0) {
        maxWidth = MAX(image.size.width, image.size.height);
    }
    float width = image.size.width*image.scale;
    float height = image.size.height*image.scale;
    CGSize newSize = CGSizeZero;
    maxWidth = maxWidth*2;
    CGFloat percent = MIN(maxWidth/width, maxWidth/height);
    int newWidth = (width * percent);
    int newHeight = height * percent;
    newSize = CGSizeMake(newWidth,newHeight);
    
    
    CGRect rect = CGRectMake(0, 0, newSize.width, newSize.height);
    UIGraphicsBeginImageContext(newSize);
    [image drawInRect:rect];
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return imageCopy;
}

+ (UIImage*) saclePublishImage:(UIImage *)image
                  withMaxWidth:(NSInteger) maxWidth
                 withMaxHeight:(NSInteger) maxHeight
{
    CGFloat width = image.size.width;
    CGFloat height = image.size.height;
    NSLog(@"saclePublishImage size: width: %f height: %f", width, height);
    
    long totalArea = width * height;
    long totalMaxArea = maxWidth * maxHeight;
    
    if (totalArea <= totalMaxArea) {
        return image;
    }
    
    CGSize newSize = CGSizeZero;
    if (width > maxWidth && height > maxHeight) {
        CGFloat percent = 1.0f;
        percent = MAX(maxWidth/width, maxHeight/height);
        int w = width * percent;
        int h = height * percent;
        newSize = CGSizeMake(w, h);
    }else {
        CGFloat scale = totalArea / totalMaxArea;
        if (scale == 0) {
            ++scale;
        }
        int w = width / scale;
        int h = height / scale;
        newSize = CGSizeMake(w, h);
    }
    
    //COMMON_LOG(@"最后输出的区域：%@", NSStringFromCGSize(newSize));
    
    // 创建一个bitmap的context
    // 并把它设置成为当前正在使用的context
    UIGraphicsBeginImageContext(newSize);
    
    // 绘制改变大小的图片
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    
    // 从当前context中创建一个改变大小后的图片
    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    
    // 使当前的context出堆栈
    UIGraphicsEndImageContext();
    
    // 返回新的改变大小后的图片
    return scaledImage;
    
    
}

// 缩放图片 UIImage
+ (UIImage *)scaleAndRotateImage:(UIImage *)image
          withMaxResolutionWidth:(NSInteger) maxResolutionWidth
           orMaxResolutionHeight:(NSInteger) maxResolutionHeight
{
    
    CGImageRef imgRef = image.CGImage;
    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);
    
    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, width, height);
    
    NSLog(@"size: width: %f height: %f", bounds.size.width, bounds.size.height);
    
    UIImageOrientation orient = image.imageOrientation;
    if ( orient == UIImageOrientationLeftMirrored ||
        orient == UIImageOrientationLeft ||
        orient == UIImageOrientationRightMirrored ||
        orient == UIImageOrientationRight)
    {
        if (width > maxResolutionHeight) {
            bounds.size.width = maxResolutionHeight;
            bounds.size.height = bounds.size.width * height / width;
        }
        if (height > maxResolutionWidth) {
            bounds.size.height = maxResolutionWidth;
            bounds.size.width = bounds.size.height * width / height;
        }
    }
    else
    {
        if (height > maxResolutionHeight) {
            bounds.size.height = maxResolutionHeight;
            bounds.size.width = bounds.size.height * width / height;
        }
        if (width > maxResolutionWidth) {
            bounds.size.width = maxResolutionWidth;
            bounds.size.height = bounds.size.width * height / width;
        }
    }
    
    //NSLog(@"output size: width: %f height: %f", bounds.size.width, bounds.size.height);
    
    CGFloat scaleRatio = bounds.size.width / width;
    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
    CGFloat boundHeight;
    
    NSLog(@"UIImageOrientation %d", orient);
    switch(orient) {
        case UIImageOrientationUp:
            transform = CGAffineTransformIdentity;
            break;
        case UIImageOrientationUpMirrored:
            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;
        case UIImageOrientationDown:
            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;
        case UIImageOrientationLeftMirrored:
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;
        case UIImageOrientationLeft:
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;
        case UIImageOrientationRightMirrored:
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;
        case UIImageOrientationRight:
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;
        default:
            [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
    }
    
    UIGraphicsBeginImageContext(bounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
        CGContextScaleCTM(context, -scaleRatio, scaleRatio);
        CGContextTranslateCTM(context, -height, 0);
    } else {
        CGContextScaleCTM(context, scaleRatio, -scaleRatio);
        CGContextTranslateCTM(context, 0, -height);
    }
    CGContextConcatCTM(context, transform);
    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return imageCopy;
}

// 为图片添加边框
+ (UIImage*)imageWithBorderFromImage:(UIImage*)source withBorderSize:(float)borderSize {
    CGSize size = [source size];
    UIGraphicsBeginImageContext(size);
    CGRect rect = CGRectMake(0, 0, size.width, size.height);
    [source drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, borderSize);
    CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
    CGContextStrokeRect(context, rect);
    
    UIImage *borderedImage=  UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return borderedImage;
}


+ (UIImage*)imageWithRoundedFromImage:(UIImage*)source
                           withRadius: (CGFloat) radius
                        andDesirtSize:(CGSize) desSize
{
    UIGraphicsBeginImageContext(desSize);
    CGRect rect = CGRectMake(0, 0, desSize.width, desSize.height);
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    CGContextBeginPath(context);
    CGContextSaveGState(context);
    
    if (radius == 0) {
        CGContextAddRect(context, rect);
    } else {
        CGContextScaleCTM(context, radius, radius);
        float fw = desSize.width / radius;
        float fh = desSize.height / radius;
        
        CGContextMoveToPoint(context, fw, fh/2);
        CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
        CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
        CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
        CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
    }
    
    CGContextClosePath(context);
    CGContextRestoreGState(context);
    
    CGContextClip(context);
    
    [source drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];
    
    UIImage *borderedImage=  UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return borderedImage;
}

#pragma mark -
#pragma mark 图片处理

+ (UIImage *) addText:(UIImage *)img text:(NSString *)text1 text:(NSString *)text2{
    int w = img.size.width;
    int h = img.size.height;
    //lon = h - lon;
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
    
    CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);
    CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1);
    char* text = (char *)[text1 cStringUsingEncoding:NSASCIIStringEncoding];// "05/05/09";
    CGContextSelectFont(context, "Arial", 12, kCGEncodingMacRoman);
    CGContextSetTextDrawingMode(context, kCGTextFill);
    CGContextSetRGBFillColor(context, 255, 255, 255, 1);
    
    //rotate text
    
    //CGContextSetTextMatrix(context, CGAffineTransformMakeRotation( -M_PI/4 ));
    CGContextShowTextAtPoint(context, 30, 8, text, strlen(text));
    
    CGImageRef imageMasked = CGBitmapContextCreateImage(context);
    
    CGContextRelease(context);
    
    context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
    CGContextDrawImage(context, CGRectMake(0, 0, w, h), [UIImage imageWithCGImage:imageMasked].CGImage);
    CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1);
    text = (char *)[text2 cStringUsingEncoding:NSASCIIStringEncoding];// "05/05/09";
    CGContextSelectFont(context, "Arial", 12, kCGEncodingMacRoman);
    CGContextSetTextDrawingMode(context, kCGTextFill);
    CGContextSetRGBFillColor(context, 255, 255, 255, 1);
    
    CGContextShowTextAtPoint(context, 90, 8, text, strlen(text));
    CGImageRef imgRef = CGBitmapContextCreateImage(context);
    UIImage *resultImage = [UIImage imageWithCGImage:imgRef];
    
    CGContextRelease(context);
    CGImageRelease(imageMasked);
    CGImageRelease(imgRef);
    CGColorSpaceRelease(colorSpace);
    
    return resultImage;
}


+ (UIImage *) mergeImage:(UIImage *)imgA withImage:(UIImage *)imgB {
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(imgA.size.width, imgA.size.height), YES, 0.0);
    
    [imgA drawAtPoint: CGPointMake(0,0)];
    
    [imgB drawAtPoint: CGPointMake(0,0)
            blendMode: kCGBlendModeNormal // you can play with this
                alpha: 1]; // 0 - 1
    
    UIImage *answer = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return answer;
}

+ (UIImage *) mergeImage:(UIImage *)imgA withLogo: (UIImage *) imgB withText: (NSString *) baseString
{
    CGFloat w = imgA.size.width;
    CGFloat h = imgA.size.height;
    
    //CGFloat logoW = imgB.size.width;
    CGFloat logoH = imgB.size.height;
    
    UIGraphicsBeginImageContext(CGSizeMake(w, h));
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    [imgA drawAtPoint: CGPointMake(0.0f, 0.0f)];
    
    [imgB drawAtPoint: CGPointMake(0.0f, h - logoH)];
    
    {
        CGContextSaveGState(context);
        
        CGContextTranslateCTM(context, 0, h);
        CGContextScaleCTM(context, 1, -1);
        
        const char *text = [baseString cStringUsingEncoding: NSASCIIStringEncoding];
        CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 1.0f);
        CGContextSelectFont(context, "Arial", 12, kCGEncodingMacRoman);
        CGContextSetTextDrawingMode(context, kCGTextFill);
        
        CGContextShowTextAtPoint(context, 30, logoH / 2 - 6, text, strlen(text));
        CGContextRestoreGState(context);
    }
    
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return outputImage;
}

+ (UIImage *) mergeImage:(UIImage *)imgA
                withLogo: (UIImage *) imgB
                withText: (NSString *) baseString
              goodResult: (NSInteger) goodRes
               badResult: (NSInteger) badRes
                   Total: (NSInteger) total
{
    CGFloat w = imgA.size.width;
    CGFloat h = imgA.size.height;
    
    //CGFloat logoW = imgB.size.width;
    CGFloat logoH = imgB.size.height;
    
    UIGraphicsBeginImageContext(CGSizeMake(w, h));
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    [imgA drawAtPoint: CGPointMake(0.0f, 0.0f)];
    
    [imgB drawAtPoint: CGPointMake(0.0f, h - logoH)];
    
    {
        CGContextSaveGState(context);
        
        CGContextTranslateCTM(context, 0, h);
        CGContextScaleCTM(context, 1, -1);
        
        CGContextSelectFont(context, "Arial", 12, kCGEncodingMacRoman);
        CGContextSetTextDrawingMode(context, kCGTextFill);
        
        char temp[16];
        sprintf(temp, "%ld%%", (long)goodRes);
        CGContextSetRGBFillColor(context, 0.50f, 0.82f, 0.22f, 1.0f);
        CGContextShowTextAtPoint(context, 20, 45, temp, strlen(temp));
        
        sprintf(temp, "%ld%%", (long)badRes);
        CGContextSetRGBFillColor(context, 0.94f, 0.29f, 0.12f, 1.0f);
        CGContextShowTextAtPoint(context, 65, 45, temp, strlen(temp));
        
        sprintf(temp, "%ld", (long)total);
        CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 1.0f);
        CGContextShowTextAtPoint(context, 133, 45, temp, strlen(temp));
        
        const char *text = [baseString cStringUsingEncoding: NSASCIIStringEncoding];
        CGContextShowTextAtPoint(context, 30, 20, text, strlen(text));
        
        CGContextRestoreGState(context);
    }
    
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return outputImage;
}




+ (UIImage *)createImageFromView:(UIView *)theView
{
    return [ImageUtility createImageFromView:theView frame:theView.bounds];
}


+ (UIImage *)createImageFromView:(UIView *)theView frame:(CGRect)frame{
    UIGraphicsBeginImageContextWithOptions(frame.size, YES, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, -frame.origin.x, -frame.origin.y);
    [theView.layer renderInContext:context];
    UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return renderedImage;
}


+ (UIImage *)blurryImage:(UIImage *)image boxSize:(int)boxSize{
    
    boxSize = boxSize - (boxSize % 2) + 1;
    
    CGImageRef img = image.CGImage;
    
    vImage_Buffer inBuffer, outBuffer;
    vImage_Error error;
    
    void *pixelBuffer;
    
    CGDataProviderRef inProvider = CGImageGetDataProvider(img);
    CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
    
    inBuffer.width = CGImageGetWidth(img);
    inBuffer.height = CGImageGetHeight(img);
    inBuffer.rowBytes = CGImageGetBytesPerRow(img);
    
    inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
    
    pixelBuffer = malloc(CGImageGetBytesPerRow(img) *
                         CGImageGetHeight(img));
    
    if(pixelBuffer == NULL)
        NSLog(@"No pixelbuffer");
    
    outBuffer.data = pixelBuffer;
    outBuffer.width = CGImageGetWidth(img);
    outBuffer.height = CGImageGetHeight(img);
    outBuffer.rowBytes = CGImageGetBytesPerRow(img);
    
    error = vImageBoxConvolve_ARGB8888(&inBuffer,
                                       &outBuffer,
                                       NULL,
                                       0,
                                       0,
                                       boxSize,
                                       boxSize,
                                       NULL,
                                       kvImageEdgeExtend);
    
    
    if (error) {
        NSLog(@"error from convolution %ld", error);
    }
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(
                                             outBuffer.data,
                                             outBuffer.width,
                                             outBuffer.height,
                                             8,
                                             outBuffer.rowBytes,
                                             colorSpace,
                                             kCGImageAlphaNoneSkipLast);
    CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
    UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
    
    //clean up
    CGContextRelease(ctx);
    CGColorSpaceRelease(colorSpace);
    
    free(pixelBuffer);
    CFRelease(inBitmapData);
    
    CGImageRelease(imageRef);
    
    return returnImage;
}



+ (UIImage*)stackBlurWithImage:(UIImage *)image inradius:(NSUInteger)inradius
{
    long radius=inradius; // Transform unsigned into signed for further operations
    
    if (radius<1){
        return image;
    }
    // Suggestion xidew to prevent crash if size is null
    if (CGSizeEqualToSize(image.size, CGSizeZero)) {
        return image;
    }
    
    //	return [other applyBlendFilter:filterOverlay  other:self context:nil];
    // First get the image into your data buffer
    CGImageRef inImage = image.CGImage;
    
    //bug:表现图片变黑，原因，ctx为nil。
    //    int nbPerCompt=CGImageGetBitsPerPixel(inImage);
    //    if(nbPerCompt!=32){
    UIImage *tmpImage=[ImageUtility normalizeWithImage:image];
    inImage=tmpImage.CGImage;
    //    }
    if (!inImage) {
        NSLog(@"stackBlurWithImage fail!!!");
        return image;
    }
    CFDataRef m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));
    UInt8 * m_PixelBuf=malloc(CFDataGetLength(m_DataRef));
    CFDataGetBytes(m_DataRef,
                   CFRangeMake(0,CFDataGetLength(m_DataRef)) ,
                   m_PixelBuf);
    
    CGContextRef ctx = CGBitmapContextCreate(m_PixelBuf,
                                             CGImageGetWidth(inImage),
                                             CGImageGetHeight(inImage),
                                             CGImageGetBitsPerComponent(inImage),
                                             CGImageGetBytesPerRow(inImage),
                                             CGImageGetColorSpace(inImage),
                                             CGImageGetBitmapInfo(inImage)
                                             );
    
    
    long w=CGImageGetWidth(inImage);
    long h=CGImageGetHeight(inImage);
    long wm=w-1;
    long hm=h-1;
    long wh=w*h;
    long div=radius+radius+1;
    
    long *r=malloc(wh*sizeof(int));
    long *g=malloc(wh*sizeof(int));
    long *b=malloc(wh*sizeof(int));
    memset(r,0,wh*sizeof(int));
    memset(g,0,wh*sizeof(int));
    memset(b,0,wh*sizeof(int));
    long rsum,gsum,bsum,x,y,i,p,yp,yi,yw;
    long *vmin = malloc(sizeof(int)*MAX(w,h));
    memset(vmin,0,sizeof(int)*MAX(w,h));
    long divsum=(div+1)>>1;
    divsum*=divsum;
    long *dv=malloc(sizeof(int)*(256*divsum));
    for (i=0;i<256*divsum;i++){
        dv[i]=(i/divsum);
    }
    
    yw=yi=0;
    
    long *stack=malloc(sizeof(int)*(div*3));
    long stackpointer;
    long stackstart;
    long *sir;
    long rbs;
    long r1=radius+1;
    long routsum,goutsum,boutsum;
    long rinsum,ginsum,binsum;
    memset(stack,0,sizeof(int)*div*3);
    
    for (y=0;y<h;y++){
        rinsum=ginsum=binsum=routsum=goutsum=boutsum=rsum=gsum=bsum=0;
        
        for(long i=-radius;i<=radius;i++){
            sir=&stack[(i+radius)*3];
            /*			p=m_PixelBuf[yi+MIN(wm,MAX(i,0))];
             sir[0]=(p & 0xff0000)>>16;
             sir[1]=(p & 0x00ff00)>>8;
             sir[2]=(p & 0x0000ff);
             */
            long offset=(yi+MIN(wm,MAX(i,0)))*4;
            sir[0]=m_PixelBuf[offset];
            sir[1]=m_PixelBuf[offset+1];
            sir[2]=m_PixelBuf[offset+2];
            
            rbs=r1-abs((int)i);
            rsum+=sir[0]*rbs;
            gsum+=sir[1]*rbs;
            bsum+=sir[2]*rbs;
            if (i>0){
                rinsum+=sir[0];
                ginsum+=sir[1];
                binsum+=sir[2];
            } else {
                routsum+=sir[0];
                goutsum+=sir[1];
                boutsum+=sir[2];
            }
        }
        stackpointer=radius;
        
        
        for (x=0;x<w;x++){
            r[yi]=dv[rsum];
            g[yi]=dv[gsum];
            b[yi]=dv[bsum];
            
            rsum-=routsum;
            gsum-=goutsum;
            bsum-=boutsum;
            
            stackstart=stackpointer-radius+div;
            sir=&stack[(stackstart%div)*3];
            
            routsum-=sir[0];
            goutsum-=sir[1];
            boutsum-=sir[2];
            
            if(y==0){
                vmin[x]=MIN(x+radius+1,wm);
            }
            
            /*			p=m_PixelBuf[yw+vmin[x]];
             
             sir[0]=(p & 0xff0000)>>16;
             sir[1]=(p & 0x00ff00)>>8;
             sir[2]=(p & 0x0000ff);
             */
            long offset=(yw+vmin[x])*4;
            sir[0]=m_PixelBuf[offset];
            sir[1]=m_PixelBuf[offset+1];
            sir[2]=m_PixelBuf[offset+2];
            rinsum+=sir[0];
            ginsum+=sir[1];
            binsum+=sir[2];
            
            rsum+=rinsum;
            gsum+=ginsum;
            bsum+=binsum;
            
            stackpointer=(stackpointer+1)%div;
            sir=&stack[((stackpointer)%div)*3];
            
            routsum+=sir[0];
            goutsum+=sir[1];
            boutsum+=sir[2];
            
            rinsum-=sir[0];
            ginsum-=sir[1];
            binsum-=sir[2];
            
            yi++;
        }
        yw+=w;
    }
    for (x=0;x<w;x++){
        rinsum=ginsum=binsum=routsum=goutsum=boutsum=rsum=gsum=bsum=0;
        yp=-radius*w;
        for(i=-radius;i<=radius;i++){
            yi=MAX(0,yp)+x;
            
            sir=&stack[(i+radius)*3];
            
            sir[0]=r[yi];
            sir[1]=g[yi];
            sir[2]=b[yi];
            
            rbs=r1-abs((int)i);
            
            rsum+=r[yi]*rbs;
            gsum+=g[yi]*rbs;
            bsum+=b[yi]*rbs;
            
            if (i>0){
                rinsum+=sir[0];
                ginsum+=sir[1];
                binsum+=sir[2];
            } else {
                routsum+=sir[0];
                goutsum+=sir[1];
                boutsum+=sir[2];
            }
            
            if(i<hm){
                yp+=w;
            }
        }
        yi=x;
        stackpointer=radius;
        for (y=0;y<h;y++){
            //			m_PixelBuf[yi]=0xff000000 | (dv[rsum]<<16) | (dv[gsum]<<8) | dv[bsum];
            long offset=yi*4;
            m_PixelBuf[offset]=dv[rsum];
            m_PixelBuf[offset+1]=dv[gsum];
            m_PixelBuf[offset+2]=dv[bsum];
            rsum-=routsum;
            gsum-=goutsum;
            bsum-=boutsum;
            
            stackstart=stackpointer-radius+div;
            sir=&stack[(stackstart%div)*3];
            
            routsum-=sir[0];
            goutsum-=sir[1];
            boutsum-=sir[2];
            
            if(x==0){
                vmin[y]=MIN(y+r1,hm)*w;
            }
            p=x+vmin[y];
            
            sir[0]=r[p];
            sir[1]=g[p];
            sir[2]=b[p];
            
            rinsum+=sir[0];
            ginsum+=sir[1];
            binsum+=sir[2];
            
            rsum+=rinsum;
            gsum+=ginsum;
            bsum+=binsum;
            
            stackpointer=(stackpointer+1)%div;
            sir=&stack[(stackpointer)*3];
            
            routsum+=sir[0];
            goutsum+=sir[1];
            boutsum+=sir[2];
            
            rinsum-=sir[0];
            ginsum-=sir[1];
            binsum-=sir[2];
            
            yi+=w;
        }
    }
    free(r);
    free(g);
    free(b);
    free(vmin);
    free(dv);
    free(stack);
    CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
    CGContextRelease(ctx);
    
    UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CFRelease(m_DataRef);
    free(m_PixelBuf);
    return finalImage;
}




+ (UIImage *)normalizeWithImage:(UIImage *)image{
    
    CGColorSpaceRef genericColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef thumbBitmapCtxt = CGBitmapContextCreate(NULL,
                                                         
                                                         image.size.width,
                                                         image.size.height,
                                                         8, (4 * image.size.width),
                                                         genericColorSpace,
                                                         kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(genericColorSpace);
    CGContextSetInterpolationQuality(thumbBitmapCtxt, kCGInterpolationDefault);
    CGRect destRect = CGRectMake(0, 0, image.size.width, image.size.height);
    CGContextDrawImage(thumbBitmapCtxt, destRect, image.CGImage);
    CGImageRef tmpThumbImage = CGBitmapContextCreateImage(thumbBitmapCtxt);
    CGContextRelease(thumbBitmapCtxt);
    UIImage *result = [UIImage imageWithCGImage:tmpThumbImage];
    CGImageRelease(tmpThumbImage);
    
    return result;
}



+ (UIImage *)blurredImageWithRadius:(CGFloat)radius image:(UIImage *)image iterations:(NSUInteger)iterations
{
    //image must be nonzero size
    if (floorf(image.size.width) * floorf(image.size.height) <= 0.0f) return image;
    
    //boxsize must be an odd integer
    int boxSize = radius * image.scale;
    if (boxSize % 2 == 0) boxSize ++;
    
    //create image buffers
    CGImageRef imageRef = image.CGImage;
    vImage_Buffer buffer1, buffer2;
    buffer1.width = buffer2.width = CGImageGetWidth(imageRef);
    buffer1.height = buffer2.height = CGImageGetHeight(imageRef);
    buffer1.rowBytes = buffer2.rowBytes = CGImageGetBytesPerRow(imageRef);
    CFIndex bytes = buffer1.rowBytes * buffer1.height;
    buffer1.data = malloc(bytes);
    buffer2.data = malloc(bytes);
    
    //create temp buffer
    void *tempBuffer = malloc(vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, NULL, 0, 0, boxSize, boxSize,
                                                         NULL, kvImageEdgeExtend + kvImageGetTempBufferSize));
    
    //copy image data
    CFDataRef dataSource = CGDataProviderCopyData(CGImageGetDataProvider(imageRef));
    memcpy(buffer1.data, CFDataGetBytePtr(dataSource), bytes);
    CFRelease(dataSource);
    
    for (int i = 0; i < iterations; i++)
    {
        //perform blur
        vImageBoxConvolve_ARGB8888(&buffer1, &buffer2, tempBuffer, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
        
        //swap buffers
        void *temp = buffer1.data;
        buffer1.data = buffer2.data;
        buffer2.data = temp;
    }
    
    //free buffers
    free(buffer2.data);
    free(tempBuffer);
    
    //create image context from buffer
    CGContextRef ctx = CGBitmapContextCreate(buffer1.data, buffer1.width, buffer1.height,
                                             8, buffer1.rowBytes, CGImageGetColorSpace(imageRef),
                                             CGImageGetBitmapInfo(imageRef));
    
    //create image from context
    imageRef = CGBitmapContextCreateImage(ctx);
    UIImage *blurImage = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
    CGImageRelease(imageRef);
    CGContextRelease(ctx);
    free(buffer1.data);
    return blurImage;
}



+ (UIImage *) addImage:(UIImage *)imgA toImage:(UIImage *)imgB {
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(imgB.size.width, imgB.size.height), YES, 0.0);
    
    
    //    [imgB drawAtPoint: CGPointMake(0,0)
    //			blendMode: kCGBlendModeOverlay 
    //				alpha: 1]; // 0 - 1
    //	[imgA drawAtPoint: CGPointMake(0,0)];
    
    [imgB drawAtPoint: CGPointMake(imgB.size.width/2,imgB.size.height/2)];
    [imgA drawAtPoint: CGPointMake(0,0)
            blendMode: kCGBlendModeNormal
                alpha: 1]; // 0 - 1
    
    
    
    
    UIImage *answer = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return answer;
}


/*!
 * add geolocation and comment to image
 */
+(NSData *)geoTaggedDataWithLocation:(CLLocation *)location image:(UIImage *)image{
    NSData *data = UIImageJPEGRepresentation(image, 1.0);
    return [ImageUtility geoTaggedData:data withLocation:location imageTime:nil];
}

/*!
 * add geolocation and comment to image
 */
+(NSData *)geoTaggedData:(NSData *)data
            withLocation:(CLLocation *)location
               imageTime:(NSDate *)imageTime
{
    CGImageSourceRef img = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    NSMutableDictionary* exifDict = [[NSMutableDictionary alloc] init];
    NSMutableDictionary* locDict = [[NSMutableDictionary alloc] init];
    if (imageTime) {
        NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:@"yyyy:MM:dd HH:mm:ss"];
        NSString* datetime = [dateFormatter stringFromDate:imageTime];
        [exifDict setObject:datetime forKey:(NSString*)kCGImagePropertyExifDateTimeOriginal];
        [exifDict setObject:datetime forKey:(NSString*)kCGImagePropertyExifDateTimeDigitized];
    }
    
    [locDict setObject:location.timestamp forKey:(NSString*)kCGImagePropertyGPSTimeStamp];
    if (location.coordinate.latitude <0.0){
        [locDict setObject:@"S" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
    }
    else{
        [locDict setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
    }
    
    [locDict setObject:[NSNumber numberWithFloat:location.coordinate.latitude]
                forKey:(NSString*)kCGImagePropertyGPSLatitude];
    if (location.coordinate.longitude < 0.0){
        [locDict setObject:@"W" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
    }
    else{
        [locDict setObject:@"E" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
    }
    [locDict setObject:[NSNumber numberWithFloat:location.coordinate.longitude] forKey:(NSString*)kCGImagePropertyGPSLongitude];
    
    NSMutableData* imageData = [[NSMutableData alloc] init];
    CGImageDestinationRef dest = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, CGImageSourceGetType(img), 1, NULL);
    
    NSMutableDictionary *metadata =
    [NSMutableDictionary dictionaryWithObjectsAndKeys:
     locDict,  (NSString*)kCGImagePropertyGPSDictionary,
     exifDict, (NSString*)kCGImagePropertyExifDictionary, nil];
    CGImageDestinationAddImageFromSource(dest, img, 0, (__bridge CFDictionaryRef)metadata);
    CGImageDestinationFinalize(dest);
    CFRelease(img);
    CFRelease(dest);
    return imageData;
}
/*!
 * load metadata
 */
+(NSDictionary *)extractMetadata:(NSData *)data
{
    CGImageSourceRef image = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithDictionary:(__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(image, 0, nil)];
    CFRelease(image);
    return metadata;
}

/**
 *	@brief	对缩略图进行压缩
 *
 *	@param 	dataLength 	图片数据的大小
 *
 *	@return	压缩比例
 */
+(CGFloat)compressionThumbImage:(NSInteger)dataLength
{
    /**
     *  @brief 超10k，压缩成5k左右
     */
    CGFloat compression = 1.0;
    if (dataLength > kThumbMaxDataLength_10) {
        
        compression = (kThumbMaxDataLength_5*0.1)/ (dataLength*0.1);
        
    }
    return compression;
    
}

@end
